<html>
	<head>
		<title>JSEV additionalItems Test</title>
		<script type="application/javascript" src="../methods.Object.js"></script>
		<script type="application/javascript" src="../methods.Array.js"></script>
		<script type="application/javascript" src="../JSON.schema.reg.js"></script>
		<script type="application/javascript" src="../JSON.path.js"></script>
		<script type="application/javascript" src="../JSON.schema.err.js"></script>
		<script type="application/javascript" src="../JSON.schema.err.messages.en.js"></script>
		<script type="application/javascript" src="../JSON.schema.ext.walker.js"></script>
		<script type="application/javascript" src="../JSON.schema.ext.js"></script>
		<script type="application/javascript">
			function validTest() {
				var schemaA = {"id": "schemaA", "type": "array"},
					schemaB = {"id": "schemaB", "type": ["array", "integer"]},
					schemaC = {"id": "schemaC", "items": {"type": "string"}},
					schemaD = {"id": "schemaD", "items": [{"type": "string"}]},
					schemaE = {"id": "schemaE", "items": {"type": "number"}},
					schemaF = {"id": "schemaF", "maxItems": 2},
					schemaG = {"id": "schemaG", "items": [{"type": "number"}, {"type": "integer"}]},
					schemaH = {"id": "schemaH", "items": [{"type": "number"}, {"type": "integer"}], "additionalItems": false},
					schemaI = {"id": "schemaI", "items": [{"type": "number"}, {"type": "number"}], "additionalItems": {"type": "integer"}},
					schemaJ = {"id": "schemaJ", "items": [{"type": "number"}, {"type": "number"}], "additionalItems": {"type": "integer"}, "maxItems": 3},
					/** Shouldn't produce RequiredTypeError RTE000 (Restriction requires type array) */
					schema0 = {"items": [{"type": "number"}], "additionalItems": {"type": "string"}},
					schema1 = {"type": "array", "items": [{"type": "number"}], "additionalItems": {"type": "string"}},
					schema2 = {"type": ["array", "integer"], "items": [{"type": "number"}], "additionalItems": {"type": "string"}},
					schema3 = {"type": "schemaA", "items": [{"type": "number"}], "additionalItems": {"type": "string"}},
					schema4 = {"extends": "schemaA", "items": [{"type": "number"}], "additionalItems": {"type": "string"}},
					schema5 = {"type": "schemaB", "items": [{"type": "number"}], "additionalItems": {"type": "string"}},
					schema6 = {"extends": "schemaB", "items": [{"type": "number"}], "additionalItems": {"type": "string"}},
					/** Shouldn't produce RequiredTypeError RTE001 (no items restriction, must be in current schema) */
					schema7 = {"items": [{"type": "string"}], "additionalItems": {"type": "string"}},
					/** Shouldn't produce SubTypeError STE004 (current restriction must be subtype of super items) */
					schema8 = {"type": "schemaE", "items": [{"type": "integer"}], "additionalItems": {"type": "integer"}},
					schema9 = {"extends": "schemaE", "items": [{"type": "integer"}], "additionalItems": {"type": "integer"}},
					/** Shouldn't produce InvalidValueError IVE008 (items has maxItems number of types so additionalItems must have value false) */
					schema10 = {"items": [{"type": "number"}, {"type": "string"}], "maxItems": 2, "additionalItems": false},
					schema11 = {"type": "schemaF", "items": [{"type": "number"}, {"type": "string"}], "additionalItems": false},
					schema12 = {"extends": "schemaF", "items": [{"type": "number"}, {"type": "string"}], "additionalItems": false},
					/** Shouldn't produce InvalidValueError IVE009 (super items tuple is size 2, super additionalItems is false, and current
					    items tuple size 2, therefore there must be no additionalItems restriction or it must be false) */
					schema13 = {"type": "schemaH", "items": [{"type": "number"}, {"type": "integer"}]},
					schema14 = {"extends": "schemaH", "items": [{"type": "number"}, {"type": "integer"}]},
					schema15 = {"type": "schemaH", "items": [{"type": "number"}, {"type": "integer"}], "additionalItems": false},
					schema16 = {"extends": "schemaH", "items": [{"type": "number"}, {"type": "integer"}], "additionalItems": false},
					/** Shouldn't produce SubTypeError STE009 (additionalItems not a subtype of remaining super items) */
					schema17 = {"type": "schemaG", "items": [{"type": "integer"}], "additionalItems": {"type": "integer"}},
					schema18 = {"extends": "schemaG", "items": [{"type": "integer"}], "additionalItems": {"type": "integer"}},
					schema19 = {"type": "schemaH", "items": [{"type": "integer"}], "additionalItems": {"type": "integer"}},
					schema20 = {"extends": "schemaH", "items": [{"type": "integer"}], "additionalItems": {"type": "integer"}},
					/** Shouldn't produce SubTypeError STE010 (additionalItems not a subtype of super additionalItems) */
					schema21 = {"type": "schemaI", "items": [{"type": "integer"}], "additionalItems": {"type": "integer"}},
					schema22 = {"extends": "schemaI", "items": [{"type": "integer"}], "additionalItems": {"type": "integer"}},
					schema23 = {"type": "schemaJ", "items": [{"type": "integer"}], "additionalItems": {"type": "integer"}},
					schema24 = {"extends": "schemaJ", "items": [{"type": "integer"}], "additionalItems": {"type": "integer"}},
					schema25 = {"type": "schemaI", "maxItems": 3, "items": [{"type": "integer"}], "additionalItems": {"type": "integer"}},
					schema26 = {"extends": "schemaI", "maxItems": 3, "items": [{"type": "integer"}], "additionalItems": {"type": "integer"}},
					schemasToValidate = [
						schema0, schema1, schema2, schema3, schema4, schema5, schema6,
						schema7,
						schema8, schema9,
						schema10, schema11, schema12,
						schema13, schema14, schema15, schema16,
						schema17, schema18, schema19, schema20,
						schema21, schema22, schema23, schema24, schema25, schema26
					],
					retVal = undefined;

				try {
					JSON.schema.registry.unregister("*");
					JSON.schema.registry.register([schemaA, schemaB, schemaC, schemaD, schemaE, schemaF, schemaG, schemaH, schemaI, schemaJ]);
				} catch (e) {
					console.error("Type registration failed: ", e);
				}

				for (var i in schemasToValidate) {
					retVal = JSON.schema.ext.validate(schemasToValidate[i]);
					if (retVal.valid) {
						console.info("Test " + i + " passed!", retVal);
					} else {
						console.warn("Test " + i + " failed.", retVal);
						if (retVal.errors.length > 0) {
							console.group("Error messages:");
							for (var i in retVal.errors) {
								console.info(JSON.schema.err.localize("en", retVal.errors[i]));
							}
							console.groupEnd();
						} else {
							console.info("No errors reported.");
						}
					}
				}
			}

			function invalidTest() {
				var schemaA = {"id": "schemaA", "type": "integer"},
					schemaB = {"id": "schemaB", "type": ["array", "integer"], "disallow": "array"},
					schemaC = {"id": "schemaC", "items": {"type": "string"}},
					schemaD = {"id": "schemaD", "items": [{"type": "string"}]},
					schemaE = {"id": "schemaE", "items": {"type": "number"}},
					schemaF = {"id": "schemaF", "maxItems": 2},
					schemaG = {"id": "schemaG", "items": [{"type": "number"}, {"type": "integer"}]},
					schemaH = {"id": "schemaH", "items": [{"type": "number"}, {"type": "integer"}], "additionalItems": false},
					schemaI = {"id": "schemaI", "items": [{"type": "number"}, {"type": "number"}], "additionalItems": {"type": "integer"}},
					schemaJ = {"id": "schemaJ", "items": [{"type": "number"}, {"type": "number"}], "additionalItems": {"type": "integer"}, "maxItems": 3},
					/** RequiredTypeError RTE000 (Restriction requires type array) */
					schema0 = {"type": "integer", "items": [{"type": "number"}], "additionalItems": {"type": "string"}},
					schema1 = {"disallow": "array", "items": [{"type": "number"}], "additionalItems": {"type": "string"}},
					schema2 = {"type": ["array", "integer"], "disallow": "array", "items": [{"type": "number"}], "additionalItems": {"type": "string"}},
					schema3 = {"type": "schemaA", "items": [{"type": "number"}], "additionalItems": {"type": "string"}},
					schema4 = {"extends": "schemaA", "items": [{"type": "number"}], "additionalItems": {"type": "string"}},
					schema5 = {"type": "schemaB", "items": [{"type": "number"}], "additionalItems": {"type": "string"}},
					schema6 = {"extends": "schemaB", "items": [{"type": "number"}], "additionalItems": {"type": "string"}},
					/** RequiredTypeError RTE001 (no items restriction, must be in current schema) */
					schema7 = {"additionalItems": {"type": "string"}},
					schema8 = {"items": {"type": "string"}, "additionalItems": {"type": "string"}},
					schema9 = {"type": "schemaC", "additionalItems": {"type": "string"}},
					schema10 = {"extends": "schemaC", "additionalItems": {"type": "string"}},
					schema11 = {"type": "schemaD", "additionalItems": {"type": "string"}},
					schema12 = {"extends": "schemaD", "additionalItems": {"type": "string"}},
					/** SubTypeError STE004 (current restriction must be subtype of super items) */
					schema13 = {"type": "schemaE", "items": [{"type": "integer"}], "additionalItems": {"type": "string"}},
					schema14 = {"extends": "schemaE", "items": [{"type": "integer"}], "additionalItems": {"type": "string"}},
					/** InvalidValueError IVE008 (items has maxItems number of types so additionalItems must have value false) */
					schema15 = {"items": [{"type": "number"}, {"type": "string"}], "maxItems": 2, "additionalItems": {"type": "boolean"}},
					schema16 = {"type": "schemaF", "items": [{"type": "number"}, {"type": "string"}], "additionalItems": {"type": "boolean"}},
					schema17 = {"extends": "schemaF", "items": [{"type": "number"}, {"type": "string"}], "additionalItems": {"type": "boolean"}},
					/** InvalidValueError IVE009 (super items tuple is size 2, super additionalItems is false, and current items tuple size 2,
					    therefore there must be no additionalItems restriction or it must be false) */
					schema18 = {"type": "schemaH", "items": [{"type": "number"}, {"type": "integer"}], "additionalItems": {"type": "boolean"}},
					schema19 = {"extends": "schemaH", "items": [{"type": "number"}, {"type": "integer"}], "additionalItems": {"type": "boolean"}},
					/** SubTypeError STE009 (additionalItems not a subtype of remaining super items) */
					schema20 = {"type": "schemaG", "items": [{"type": "integer"}], "additionalItems": {"type": "string"}},
					schema21 = {"extends": "schemaG", "items": [{"type": "integer"}], "additionalItems": {"type": "string"}},
					schema22 = {"type": "schemaH", "items": [{"type": "integer"}], "additionalItems": {"type": "string"}},
					schema23 = {"extends": "schemaH", "items": [{"type": "integer"}], "additionalItems": {"type": "string"}},
					/** SubTypeError STE010 (additionalItems not a subtype of super additionalItems) */
					schema24 = {"type": "schemaI", "items": [{"type": "integer"}], "additionalItems": {"type": "number"}},
					schema25 = {"extends": "schemaI", "items": [{"type": "integer"}], "additionalItems": {"type": "number"}},
					schema26 = {"type": "schemaJ", "items": [{"type": "integer"}], "additionalItems": {"type": "number"}},
					schema27 = {"extends": "schemaJ", "items": [{"type": "integer"}], "additionalItems": {"type": "number"}},
					schema28 = {"type": "schemaI", "maxItems": 3, "items": [{"type": "integer"}], "additionalItems": {"type": "number"}},
					schema29 = {"extends": "schemaI", "maxItems": 3, "items": [{"type": "integer"}], "additionalItems": {"type": "number"}},
					errorsExpected = [
						["RTE000", "RTE000"], ["RTE000", "RTE000"], ["RTE000", "RTE000"], ["RTE000", "RTE000"], ["RTE000", "RTE000"], ["RTE000", "RTE000"], ["RTE000", "RTE000"],
						["RTE001"], ["RTE001"], ["RTE001"], ["RTE001"], ["RTE001"], ["RTE001"],
						["STE004"], ["STE004"],
						["IVE008"], ["IVE008"], ["IVE008"],
						["IVE009"], ["IVE009"],
						["STE009"], ["STE009"], ["STE009"], ["STE009"],
						["STE010"], ["STE010"], ["STE011"], ["STE011"], ["STE011"], ["STE011"]
					],
					schemasToValidate = [
						schema0, schema1, schema2, schema3, schema4, schema5, schema6,
						schema7, schema8, schema9, schema10, schema11, schema12,
						schema13, schema14,
						schema15, schema16, schema17,
						schema18, schema19,
						schema20, schema21, schema22, schema23,
						schema24, schema25, schema26, schema27, schema28, schema29
					],
					retVal = undefined;

				try {
					JSON.schema.registry.unregister("*");
					JSON.schema.registry.register([schemaA, schemaB, schemaC, schemaD, schemaE, schemaF, schemaG, schemaH, schemaI, schemaJ]);
				} catch (e) {
					console.error("Type registration failed: ", e);
				}

				function correctErrors(vRetVal, errorsExpected) {
					if (vRetVal.errors.length != errorsExpected.length)
						return false;

					var i = 0;
					for (; i < errorsExpected.length; i++) {
						if (errorsExpected[i] != vRetVal.errors[i].code) {
							return false;
						}
					}
					return true;
				}

				for (var i in schemasToValidate) {
					retVal = JSON.schema.ext.validate(schemasToValidate[i]);
					if (!retVal.valid && correctErrors(retVal, errorsExpected[i])) {
						console.info("Test " + i + " passed!", retVal);
						if (document.getElementById("showInvMsg").checked) {
							console.group("Error Messages for expected errors:");
							for (var j in retVal.errors)
								console.info(JSON.schema.err.localize("en", retVal.errors[j]));
							console.groupEnd();
						}
					} else {
						console.warn("Test " + i + " failed.", retVal);
						console.group("Reason: ");
						var loops = errorsExpected[i].length > retVal.errors.length ?
							errorsExpected[i].length : retVal.errors.length;
						var msg = "";

						if (loops == 0) {
							console.info("The schema was marked as valid yet it should have been invalid.");
						} else {
							for (var j = 0; j < loops; j++) {
								if (
									j in errorsExpected[i] && j in retVal.errors &&
									errorsExpected[i][j] == retVal.errors[j].code
								) continue;

								if (j in errorsExpected[i])
									msg += "Error Expected: " + errorsExpected[i][j];
								else
									msg += "No error expected";

								if (j in retVal.errors)
									msg += ", found: " + retVal.errors[j].code + ".";
								else
									msg += ", no error found."

								console.info(msg);
								msg = "";
							}
						}
						console.groupEnd();
					}
				}
			}
		</script>
	</head>
	<body>
		<div> Tests the `additionalItems' restriction check of JSON.schema.ext.validate </div>
		<div><button onclick="validTest();">Valid Schema Test</button></div>
		<div><button onclick="invalidTest();">Invalid Schema Test</button><input type="checkbox" id="showInvMsg"></input><label for="showInvMsg">Show Messages</label></div>
	</body>
</html>